/*
 * 软件版权: Mr.LEE
 * 修改记录:
 * 修改日期     修改人员  修改说明
 * ========    =======  ============================================
 * 2020/12/28  LJH  新增
 * ========    =======  ============================================
 */
package com.lagou.cloud.filter;

import org.apache.commons.lang.time.DateUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 功能说明:
 *
 * @author LJH
 */
@Component
public class IpFilter implements GlobalFilter, Ordered {

    private Map<String, Date> ipMap = new HashMap<>(8);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String ip = request.getRemoteAddress().getHostString();
        Date expireTime = ipMap.get(ip);
        //TODO 校验ip是否请求过于频繁
        if (expireTime == null) {
            ipMap.put(ip, DateUtils.addSeconds(new Date(), 3));
        } else {
            Date now = new Date();
            if (now.before(expireTime)) {
                //进行过滤
                response.setStatusCode(HttpStatus.SEE_OTHER);
                String responseStr = "您请求过于频繁，已被拒绝！";
                DataBuffer wrap = response.bufferFactory().wrap(responseStr.getBytes());
                return response.writeWith(Mono.just(wrap));
            } else {
                ipMap.put(ip, DateUtils.addSeconds(now, 3));
            }
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
